home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 2
/
Deutsche Edition 2.iso
/
mac
/
POWERMAC
/
C64
/
SOURCE
/
ColorVIC.c
< prev
next >
Wrap
Text File
|
1994-06-06
|
14KB
|
554 lines
/*
Commodore 64 Emulator v0.4 Earle F. Philhower III
Copyright (C) 1993-4 (st916w9r@dunx1.ocs.drexel.edu)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Processor.h"
#include "Memory.h"
#include "Error.h"
#include "Resources.h"
#include "VIC.h"
#include <QDOffscreen.h>
#include <GestaltEqu.h>
void TotalRedrawVIC(void);
void SetupColorTable(void);
OSErr CreateGDevice (PixMapHandle, GDHandle*);
void NewBitMap (PixMapHandle, Rect*);
OSErr CreateOffScreen (Rect*, short, CTabHandle, CGrafPtr*, GDHandle*);
OSErr SetUpPixMap(short, Rect*, CTabHandle, short, PixMapHandle);
/*
kPixDepth is the pixel depth of the offscreen pixmap,
kClutID is the resID of the color table,
and kDefaultRes has to do with the screen resolution of the GDevice
*/
#define kPixDepth 8
#define kClutID 1001
#define kDefaultRes 0x00480000
static Rect leftRect, rightRect, topRect, botRect, spr, screenRect;
static PixMapHandle spriteMapH;
static CTabHandle VICTab;
static GDHandle offDev;
static RGBColor VICcolors[16], back0Col, frontCol, back1Col, back2Col;
static CGrafPtr offScreenPtr;
static CGrafPtr spriteGraf; /* not used yet */
static byte VICColor[1024];
extern Rect colorWindRect, colorFullRect;
int ColorVICInitialize()
{
short err;
CTabHandle vicColors;
long gestRet;
Gestalt(gestaltQuickdrawVersion, &gestRet);
if (gestRet<gestalt8BitQD) return kNoColorSupport;
SetRect(&colorFullRect,0,0,336,210);
SetRect(&screenRect,8,5,328,205);
SetRect(&leftRect,0,0,8,210);
SetRect(&rightRect,328,0,336,210);
SetRect(&topRect,0,0,336,5);
SetRect(&botRect,0,205,336,210);
SetRect(&spr,0,0,24,21);
SetupColorTable();
ColorVICWind = (CWindowPtr)GetNewCWindow (kColorVIC, nil, (WindowPtr)-1L);
if (ColorVICWind==nil) return (kMissingResource);
vicColors = VICTab;
err = HandToHand((Handle*)&vicColors);
(**(ColorVICWind->portPixMap)).pixelType = 0;
(**(ColorVICWind->portPixMap)).cmpCount = 1;
(**(ColorVICWind->portPixMap)).cmpSize = kPixDepth;
(**(ColorVICWind->portPixMap)).pmTable = vicColors;
DisposCTable(vicColors);
spriteMapH = NewPixMap();
SetUpPixMap(kPixDepth, &spr, VICTab, kPixDepth*(spr.right-spr.left), spriteMapH);
CreateOffScreen (&colorFullRect, kPixDepth, VICTab, &offScreenPtr, &offDev);
return(kNoError);
}
void ShowColorVIC()
{
ShowWindow((WindowPtr)ColorVICWind);
SetPort((GrafPtr)ColorVICWind);
SelectWindow((WindowPtr)ColorVICWind);
}
void HideColorVIC()
{
HideWindow((WindowPtr)ColorVICWind);
}
static void DrawSprites()
{
byte spriteNum, row, *spb0, *spb1, *spb2;
word xpos, ypos, addr0, addr1, addr2;
Rect t;
/* BlockMove((**VICMapH).baseAddr, (**fullMapH).baseAddr,
GetPtrSize((**VICMapH).baseAddr));
*/
SetPortPix (spriteMapH);
for (spriteNum=0; spriteNum<8; spriteNum++)
if (VICRegister[0x15]&(1<<spriteNum)) {
xpos=VICRegister[0x00+spriteNum*2]-24;
ypos=VICRegister[0x01+spriteNum*2]-50;
xpos += (VICRegister[0x10]&(1<<spriteNum))?256:0;
t.top=ypos;t.left=xpos;
t.right=t.left+24+((VICRegister[0x1d]&(1<<spriteNum))?24:0);
t.bottom=t.top+21+((VICRegister[0x17]&(1<<spriteNum))?21:0);
addr0 = VICAddrBase+RAM[VICScreenPage+1016+spriteNum]*64;
addr1 = addr0+1;
addr2 = addr1+1;
spb0 = (byte*) ((**spriteMapH).baseAddr);
spb1 = spb0+1;
spb2 = spb0+2;
for (row=0; row<21; row++) {
spb0[row<<2]=RAM[addr0+row*3];
spb1[row<<2]=RAM[addr1+row*3];
spb2[row<<2]=RAM[addr2+row*3]; }
CopyBits((BitMap*)*spriteMapH,(BitMap*)(*(offScreenPtr->portPixMap)),&spr,&t,srcOr,nil); }
SetPortPix (offScreenPtr->portPixMap);
}
void FastDraw(byte row, byte col, word chr)
{
register short tempa, tempb, pos, h;
short line;
tempa=(row<<3)+screenRect.top; tempb=chr<<3;
Index2Color(RAM[55296+chr],&frontCol);
RGBForeColor(&frontCol);
for (line=0;line<8;line++)
for (h=(col<<3)+screenRect.left,pos=0x80;pos>0;pos>>=1,++h)
if (*(VICCharDefs+tempb+line)&pos) {
MoveTo(h,line+tempa);
Line(0,0);
}
}
void MultiDraw(byte row, byte col, word chr)
{
short tempa, tempb, line, shift, pos, h;
tempa=(row<<3)+screenRect.top; tempb=chr<<3;
Index2Color(RAM[55296+chr],&frontCol);
for (line=0;line<8;line++)
for (h=(col<<3)+screenRect.left,pos=0xC0,shift=6;pos>0;pos>>=2,h+=2,shift-=2) {
switch ((*(VICCharDefs+tempb+line)&pos)>>shift) {
case 0: RGBForeColor(&back0Col); break;
case 1: RGBForeColor(&back1Col); break;
case 2: RGBForeColor(&back2Col); break;
case 3: RGBForeColor(&frontCol); break;
}
MoveTo(h,line+tempa);
Line(1,0);
}
}
void DrawTextScreen(byte total)
{
word chr;
byte row, col;
GrafPtr savePort;
GDHandle saveDev;
Rect back;
byte* colorBase;
byte multiColor;
row=col=0;
colorBase = &RAM[55296];
GetPort (&savePort);
saveDev = GetGDevice();
SetPort ((GrafPtr)offScreenPtr);
SetGDevice (offDev);
PenSize(1,1);
multiColor = (VICRegister[0x16]&16);
Index2Color (VICRegister[0x21], &back0Col);
Index2Color (VICRegister[0x22], &back1Col);
Index2Color (VICRegister[0x23], &back2Col);
RGBBackColor (&back0Col);
/* SetOrigin(-(VICRegister[0x16]&7),-((VICRegister[0x11]&7)-3));*/
if (VICRegister[0x11]&32) /* High Res mode */
{
VICCharDefs=RAM+VICAddrBase+((VICRegister[0x18]&8)?8192:0);
for (chr=0;chr<1000;chr++) {
FastDraw(row,col,chr);
if (++col>39) {col=0;row++;} }
}
else if (total) {
EraseRect (&screenRect);
for (chr=0;chr<1000;chr++) {
if (multiColor && (RAM[55296+chr]>=8)) MultiDraw(row,col,RAM[chr+VICScreenPage]);
else FastDraw(row,col,RAM[chr+VICScreenPage]);
VICText[chr]=RAM[chr+VICScreenPage];
VICColor[chr]=RAM[55296+chr];
if (++col>39) {col=0;row++;} } }
else {
for (chr=0;chr<1000;chr++) {
if ((VICText[chr]!=RAM[chr+VICScreenPage])||(VICColor[chr]!=RAM[55296+chr])) {
SetRect (&back, (col<<3)+screenRect.left, (row<<3)+screenRect.top,
(col<<3)+screenRect.left+8, (row<<3)+screenRect.top+8);
EraseRect (&back);
if (multiColor && (RAM[55296+chr]>=8)) MultiDraw(row,col,RAM[chr+VICScreenPage]);
else FastDraw(row,col,RAM[chr+VICScreenPage]);
VICColor[chr]=RAM[55296+chr];
VICText[chr]=RAM[chr+VICScreenPage]; }
if (++col>39) {col=0;row++;} } }
/* SetOrigin(0,0);*/
SetPort (savePort);
SetGDevice (saveDev);
/* ScrollRect(&colorFullRect, VICRegister[0x16]&7,(VICRegister[0x11]&7)-3,nil);*/
}
static void DrawBorders()
{
GrafPtr savePort;
GDHandle saveDev;
RGBColor borderCol;
Rect newLeft, newRight, newTop, newBottom;
GetPort (&savePort);
saveDev = GetGDevice();
SetPort ((GrafPtr)offScreenPtr);
SetGDevice (offDev);
Index2Color (VICRegister[0x20], &borderCol);
RGBBackColor (&borderCol);
if (VICRegister[0x16]&8) {
EraseRect(&leftRect);
EraseRect(&rightRect);
}
else {
newLeft = leftRect;
OffsetRect (&newLeft, 4, 0);
InsetRect (&newLeft, -4, 0);
newRight = rightRect;
OffsetRect (&newRight, -4, 0);
InsetRect (&newRight, -4, 0);
EraseRect(&newLeft);
EraseRect(&newRight);
}
if (VICRegister[0x11]&8) {
EraseRect(&botRect);
EraseRect(&topRect);
}
else {
newBottom = botRect;
OffsetRect (&newBottom, 0, -2);
InsetRect (&newBottom, 0, -2);
newTop = topRect;
OffsetRect (&newTop, 0, 2);
InsetRect (&newTop, 0, -2);
EraseRect(&newBottom);
EraseRect(&newTop);
}
SetPort (savePort);
SetGDevice (saveDev);
}
static void CopyPortToScreen()
{
ForeColor (blackColor);
BackColor (whiteColor);
CopyBits ((BitMapPtr)*(offScreenPtr->portPixMap), &((GrafPtr)ColorVICWind)->portBits, &colorFullRect, &colorWindRect, srcCopy, nil);
}
static void BlankScreen()
{
GrafPtr savePort;
GDHandle saveDev;
RGBColor backCol;
GetPort (&savePort);
saveDev = GetGDevice();
SetPort ((GrafPtr)offScreenPtr);
SetGDevice (offDev);
Index2Color (VICRegister[0x21], &backCol);
RGBBackColor (&backCol);
EraseRect (&colorFullRect);
SetPort (savePort);
SetGDevice (saveDev);
CopyPortToScreen();
return;
}
void ColorRedrawVIC()
{
SetPort((GrafPtr)ColorVICWind);
if (!VICRegister[0x11]&16) {
BlankScreen();
return;}
DrawTextScreen(0);
DrawBorders();
if (VICRegister[0x15])
DrawSprites();
CopyPortToScreen();
}
void ColorTotalRedrawVIC()
{
SetPort((GrafPtr)ColorVICWind);
if (VICRegister[0x11]&16) /* screen blanking */
;
else
{
BlankScreen();
return;
}
DrawBorders();
DrawTextScreen(1);
if (VICRegister[0x15])
DrawSprites();
CopyPortToScreen();
}
void SetupColorTable (void)
{
VICTab = GetCTable (kClutID);
HNoPurge ((Handle)VICTab);
MoveHHi ((Handle)VICTab);
}
/*
These next three are almost verbatim from the Tech Note "Principia Off Screen"
*/
OSErr CreateGDevice (PixMapHandle basePixMap, GDHandle *retGDevice)
{
GDHandle newDevice;
ITabHandle embryoITab;
Rect deviceRect;
OSErr error;
error = noErr;
newDevice = nil;
embryoITab = nil;
newDevice = (GDHandle)NewHandle(sizeof(GDevice));
if (newDevice != nil)
{
embryoITab = (ITabHandle)NewHandleClear(2);
if (embryoITab != nil)
{
deviceRect = (**basePixMap).bounds;
(**newDevice).gdRefNum = 0;
(**newDevice).gdID = 0;
if ((**basePixMap).pixelSize <= 8)
(**newDevice).gdType = clutType;
else
(**newDevice).gdType = directType;
(**newDevice).gdITable = embryoITab;
(**newDevice).gdResPref = 4;
(**newDevice).gdSearchProc = nil;
(**newDevice).gdCompProc = nil;
(**newDevice).gdFlags = 0;
(**newDevice).gdPMap = basePixMap;
(**newDevice).gdRefCon = 0;
(**newDevice).gdNextGD = nil;
(**newDevice).gdRect = deviceRect;
(**newDevice).gdMode = -1;
(**newDevice).gdCCBytes = 0;
(**newDevice).gdCCDepth = 0;
(**newDevice).gdCCXData = 0;
(**newDevice).gdCCXMask = 0;
(**newDevice).gdReserved = 0;
if ((**basePixMap).pixelSize > 1)
SetDeviceAttribute( newDevice, gdDevType, true );
SetDeviceAttribute( newDevice, noDriver, true );
if ((**basePixMap).pixelSize <= 8)
{
MakeITable((**basePixMap).pmTable, (**newDevice).gdITable,(**newDevice).gdResPref);
error = QDError();
}
}
else
error = MemError();
}
else
error = MemError();
if (error != noErr)
{
if (embryoITab != nil)
DisposHandle( (Handle)embryoITab );
if (newDevice != nil)
DisposHandle( (Handle)newDevice );
}
else
*retGDevice = newDevice;
return error;
}
OSErr CreateOffScreen (Rect *bounds, short depth, CTabHandle colors, CGrafPtr *retPort, GDHandle *retGDevice)
{
CGrafPtr newPort;
PixMapHandle newPixMap;
GDHandle newDevice;
long qdVersion;
GrafPtr savedPort;
SignedByte savedState;
short bytesPerRow;
OSErr error;
newPort = nil;
newPixMap = nil;
newDevice = nil;
error = noErr;
if (colors != nil)
{
savedState = HGetState( (Handle)colors );
HNoPurge( (Handle)colors );
}
bytesPerRow = ((depth * (bounds->right - bounds->left) + 31) >> 5) << 2;
(void)Gestalt( gestaltQuickdrawVersion, &qdVersion );
if (depth == 1 || depth == 2 || depth == 4 || depth == 8 ||
((depth == 16 || depth == 32) && qdVersion >= gestalt32BitQD))
{
if (bytesPerRow <= 0x3FFE)
{
if (depth <= 8)
if (colors == nil)
error = paramErr; /* no table for indexed depth */
}
else
error = paramErr; /* too many bytes */
}
else
error = paramErr; /* invalid depth */
if (error == noErr)
{
newPort = (CGrafPtr)NewPtr( sizeof (CGrafPort) );
if (newPort != nil)
{
GetPort (&savedPort);
OpenCPort (newPort);
newPort->portRect = *bounds;
RectRgn (newPort->visRgn, bounds);
ClipRect (bounds);
error = SetUpPixMap (depth, bounds, colors, bytesPerRow, newPort->portPixMap);
if (error == noErr)
{
newPixMap = newPort->portPixMap;
error = CreateGDevice( newPixMap, &newDevice );
}
SetPort( savedPort );
}
else
error = MemError();
}
if (colors != nil)
HSetState( (Handle)colors, savedState );
if (error != noErr)
{
if (newPixMap != nil)
{
DisposCTable( (**newPixMap).pmTable );
DisposPtr( (**newPixMap).baseAddr );
}
if (newDevice != nil)
{
DisposHandle( (Handle)(**newDevice).gdITable );
DisposHandle( (Handle)newDevice );
}
if (newPort != nil)
{
CloseCPort( newPort );
DisposPtr( (Ptr)newPort );
}
}
else
{
*retPort = newPort;
*retGDevice = newDevice;
}
return error;
}
OSErr SetUpPixMap(short depth, Rect *bounds, CTabHandle colors, short bytesPerRow, PixMapHandle aPixMap)
{
CTabHandle newColors;
Ptr offBaseAddr;
OSErr error;
error = noErr;
newColors = nil;
offBaseAddr = nil;
if (depth <= 8)
{
newColors = colors;
error = HandToHand( (Handle *)&newColors );
}
else
{
newColors = (CTabHandle)NewHandle(sizeof(ColorTable) - sizeof(CSpecArray));
error = MemError();
}
if (error == noErr)
{
offBaseAddr = NewPtr((unsigned long)bytesPerRow * (bounds->bottom - bounds->top) );
if (offBaseAddr != nil)
{
(**aPixMap).baseAddr = offBaseAddr;
(**aPixMap).rowBytes = bytesPerRow | 0x8000;
(**aPixMap).bounds = *bounds;
(**aPixMap).pmVersion = 0;
(**aPixMap).packType = 0;
(**aPixMap).packSize = 0;
(**aPixMap).hRes = kDefaultRes;
(**aPixMap).vRes = kDefaultRes;
(**aPixMap).pixelSize = depth;
(**aPixMap).planeBytes = 0;
(**aPixMap).pmReserved = 0;
if (depth <= 8) /* PixMap is indexed */
{
(**aPixMap).pixelType = 0;
(**aPixMap).cmpCount = 1;
(**aPixMap).cmpSize = depth;
(**aPixMap).pmTable = newColors;
}
else
{
(**aPixMap).pixelType = RGBDirect;
(**aPixMap).cmpCount = 3;
if (depth == 16)
(**aPixMap).cmpSize = 5;
else
(**aPixMap).cmpSize = 8;
(**newColors).ctSeed = 3 * (**aPixMap).cmpSize;
(**newColors).ctFlags = 0;
(**newColors).ctSize = 0;
(**aPixMap).pmTable = newColors;
}
}
else
error = MemError();
}
else
newColors = nil;
if (error != noErr)
{
if (newColors != nil)
DisposCTable(newColors);
}
return error;
}